﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace PokeMod
{
    class Game
    {
        // El tamaño fijo de archivo que deben tener los juegos
        readonly static int fileSize = 0x100000;

        // Direccionamiento dentro del archivo del juego
        readonly static int DireccionNivelInicial = 0x1D203;
        readonly static int DireccionPokemonInicialA = 0x1D10E;
        readonly static int DireccionPokemonInicialB = 0x1D11F;
        readonly static int DireccionPokemonInicialC = 0x1D130;
        private int dirNombres = 0x1C21E;
        private int totalPokemon = 190;
        
        private readonly char[] chtab = new Char[]{
        	'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 0 - 15
        	'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 16 - 31
        	'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 32 - 47
        	'0','=','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 48 - 63
        	'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','\n', // 64 - 79
        	'\0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 80 - 95
        	'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 96 - 111
        	'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0',' ', // 112 - 127
        	'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', // 128 - 143
        	'Q','R','S','T','U','V','W','X','Y','Z','0','0','0','0','0','0', // 144 - 159
        	'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p', // 160 - 175
        	'q','r','s','t','u','v','w','x','y','z','0','0','0','*','0','0', // 176 - 191
        	'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 192 - 207
        	'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0', // 208 - 223
        	'0','0','=','0','0','0','0','!','0','0','0','0','0','0','0','0', // 224 - 239
        	'0','0','0','0',',','0','0','0','0','0','0','!','0','0','0','0', // 240 - 255
        }; // 80 = * es temporal
        readonly static int dirStrings = 0x80000;

        private byte[] bytes;

        public Game(byte[] bytes)
        {
            if (bytes.Length != fileSize)
            {
                throw new Exception("El tamaño del archivo es incorrecto.");
            }

            // Guardaremos toda la referencia del juego
            this.bytes = bytes;
        }

        /// <summary>
        /// Obtiene la lista completa de bytes que
        /// representan el juego completo.
        /// </summary>
        /// <returns>Arreglo de Bytes</returns>
        public byte[] GetBytes()
        {
            return this.bytes;
        }

        public Pokemon[] GetPokemons()
        {
            return null;
        }

        /// <summary>
        /// Es el nivel con que inicia el primer pokemon que te dan a elegir.
        /// </summary>
        public byte NivelInicial
        {
            get { return bytes[Game.DireccionNivelInicial]; }
            set { this.bytes[Game.DireccionNivelInicial] = value; }
        }

        public PokemonEnum PokemonInicialA
        {
            get { return (PokemonEnum) bytes[Game.DireccionPokemonInicialA]; }
            set { this.bytes[Game.DireccionPokemonInicialA] = (byte) value; }
        }

        public PokemonEnum PokemonInicialB
        {
            get { return (PokemonEnum) bytes[Game.DireccionPokemonInicialB]; }
            set { this.bytes[Game.DireccionPokemonInicialB] = (byte) value; }
        }

        public PokemonEnum PokemonInicialC
        {
            get { return (PokemonEnum) bytes[Game.DireccionPokemonInicialC]; }
            set { this.bytes[Game.DireccionPokemonInicialC] = (byte) value; }
        }
        
        public string[] GetNombres()
        {
        	string[] nombres = new String[this.totalPokemon];
        	byte[] nombre = new byte[10];
        	for( int i = 0; i < this.totalPokemon; i++ )
        		nombres[i] = this.extractText( this.dirNombres + i*10, 10 );
        	return nombres;
        }
        
        public string extractText(int index, int length)
        {
			string text = "";
        	for( int i = index; i < length+index; i++ )
        	{
        		if( this.bytes[i] == 0x0 )
        			break;
        		if( this.bytes[i] == 0xBD ) // 's
        			text += "'s";
        		if( this.bytes[i] == 0x4F ) // salto de línea
					text += "\r\n";
        		else
        			text += this.chtab[this.bytes[i]];
        	}
				
        	return text;
        }
        
        public byte[] getSegment(int index, int length)
        {
        	byte[] b = new Byte[length];
        	for( int i = index; i < index + length; i++ )
        		b[i] = this.bytes[i];
        	return b;
        }
        
        public string extractText(int index)
        {
			string text = "";
			int i = index;
			while( true ) 
			{
				if( i == this.bytes.Length || this.bytes[i] == 0 )
					break;
				if( this.bytes[i] == 0xBD ) // 's
					text += "'s";
				if( this.bytes[i] == 0x4F ) // salto de línea
					text += "\r\n";
				else
					text += this.chtab[this.bytes[i]];
				i += 1;
			}
        	return text;
        }
        
        public string[] extractAttacknames() {
        	string names = this.extractText(0xB0000);
        	return names.Split('\0');
        }
       
        public string[] extractStrings()
        {
        	List<string> strs = new List<string>();
        	int c = 0, ini = 0;
        	for( int i = Game.dirStrings; i < Game.dirStrings + 100000; i++ )
        	{
        		if( this.bytes[i] == 0x0 )
        		{
        			if( c > 0 )
        				strs.Add( this.extractText(ini,c) );
        			c = 0;
        		}
        		else
        		{
        			if( c == 0 )
        				ini = i;
        			c += 1;
        		}
        	}
        	return strs.ToArray();
        }
        
        public void SetPokemonName(int index, string name)
        {
        	// Primeramente tenemos que quitar todos los caracteres que no
        	// coincidan con la codificación de los textos del juego.
        	// A la vez vamos a evitar que sea mayor a 10 caracteres.
        	// Y asegurarse que el nombre esté en mayúsculas.
        	char[] nam = Regex.Replace((name.Length > 10 ? name.Substring(0,1) : name)
        		.ToUpper(),"/[^a-z]/i","").ToCharArray();

        	// Codificar la cadena en el formato de nombres
        	for( int i = 0; i < 10; i++ )
        		this.bytes[this.dirNombres+index * 10 + i] = (byte)( nam.Length > i
        			? nam[i] + 63 : 0x50);
        }
       
        public void changeEvolution(object id, byte level, byte pkmnev)
        {
        	if( id.GetType() == typeof(string) ) {
        		if( id == "charmander" ) {
        			this.bytes[0x3B939] = level;
        			this.bytes[0x3B93A] = pkmnev;
        		} else if( id == "cubone" ) {
        			this.bytes[0x3B2B1] = level;
        			this.bytes[0x3B2B2] = pkmnev;
        		}
        	}
        }

        public enum PokemonEnum : byte
        {
        	Bulbasaur = 153,
        	Ivysaur = 9,
        	Venusaur = 154,
        	Charmander = 176,
        	Charmeleon = 178,
        	Charizard = 180,
            Rhydon = 1,
            Kangaskhan = 2,
            NidoranMacho = 3,
            Clefairy = 4,
            Spearow = 5,
            Voltorb = 6,
            Nidoking = 7,
            Slowbro = 8,
            Exeggutor = 10,
            Lickitung = 11,
            Exeggcute = 12,
            Grimer = 13,
            Gengar = 14,
            NidoranHembra = 15,
            Nidorina = 16,
            Cubone = 17,
            Rhyhorn = 18,
            Lapras = 19,Arcanine,Mew,Gyarados,
            Shellder,Tentacool,Gastly,Scyther,Staryu,Blastoise,
            Pinsir,Tangela,MissignoA,MissignoB,Growlithe,Onix,
            Fearow,Pidgey,Slowpoke,Kadabra,Graveler,Chansey,Machoke,
            MrMime,Hitmonlee,Hitmonchan,Arbok,Parasect,Psyduck,
            Drowzee,Golem,MissignoC,Magmar,MissignoD,Electabuzz,
            Magneton,Koffing,MissignoE,Mankey,Seel,Diglett,Tauros,
            MissignoF,MissignoG,MissignoH,FarfetchD,Venonat,
            Dragonite,MissignoI,MissignoJ,MissignoK,Doduo,
            Poliwag = 71,
            Jynx = 72,
            Moltres = 73,
            Articuno = 74,
            Zapdos = 75,
            Ditto = 76,
            Meowth = 77,
            Krabby = 78,
            Vulpix = 82,
            Ninetales = 83,
            Pikachu = 84,
            Raichu = 85,
            Dratini = 88,
            Dragonair = 89,
            Kabuto = 90,
            Kabutops = 91,
            Horsea = 92,
            Seadra = 93,
            Sandshrew = 96,
            Sandslash = 97,
            Omanyte = 98,
            Omastar = 99,
            Flareon = 103,
            Jolteon = 104,
            Ekans = 108,
            Polywhirl = 110,
            Polywrath = 111,
            Weedle = 112,
            Kakuna = 113,
            Beedrill = 114,
            Dodrio = 116,
            Primeape = 117,
            Dugtrio = 118,
            Venomot = 119,
            Caterpie = 123,
            Metapod = 124,
            Butterfree = 125,
            Machamp = 126,
            Golduck = 128,
            Hypno = 129,
          	Golbat = 130,
          	Mewtwo = 131,
          	Snorlax = 132,
          	Magikarp = 133,
          	Muk = 136,
          	Kingler = 138,
          	Cloyster = 139,
          	Electrode = 141,
          	Cleafable = 142,
          	Weezing = 143,
          	Persian = 144,
          	Marowak = 145,
          	Haunter = 147,
          	Abra = 148,
          	Alakazam = 149,
          	Pidgeotto = 150,
          	Pidgeot = 151,
          	Starmie = 152,

          	Tentacruel = 155,
          	Goldeen = 157,
          	Seaking = 158,
          	Ponyta = 163,
          	Rapidash = 164,
          	Rattata = 165,
          	Raticate = 166,
          	Nidorino = 167,
          	Geodude = 169,
          	Porygon = 170,
          	Aerodactyl = 171,
          	Magnemite = 173,
          	Wartortle = 179,
            Otro1 = 181,
            Otro2 = 182,
            Otro3 = 183,
            Squirtle = 177,
            Jigglypuff = 100,
            Dewgong = 120,
            Wygglytuff = 101,
            Eeevee = 102,
            Vaporeon = 105,
            Machop = 106,
            Paras = 109
        }
    }
}
